namespace SubhadraSolutions.Sharp.Logging.Parsing
{
    using SubhadraSolutions.Sharp.Logging.Contracts;
    using SubhadraSolutions.Sharp.Utils;
    using System;
    using System.Collections.Generic;
    using System.Globalization;
    using System.IO;

    public class TextFileLogParser : ILogParser
    {
        #region Methods

        public IEnumerable<LogRecord> GetLogRecords(string fileName)
        {
            return new LogFileEnumerable(fileName, readRecord);
        }

        private LogRecord readRecord(StreamReader reader)
        {
            long position = reader.BaseStream.Position;
            var chars = new char[10];
            var c = new char[1];
            int i = -1;
            while (true)
            {
                if (reader.Read(c, 0, 1) == 1)
                {
                    if (!char.IsWhiteSpace(c[0]))
                    {
                        chars[++i] = c[0];
                    }
                    else
                    {
                        break;
                    }
                }
                else
                {
                    return null;
                }
            }
            var temp = new string(chars, 0, i + 1);
            int serialNumber = Convert.ToInt32(temp);

            List<string> sections = StringHelper.SplitString(reader, '[', ']', 3);
            while (true)
            {
                if (reader.Read(c, 0, 1) == 1)
                {
                    if (c[0] == '\n')
                    {
                        break;
                    }
                }
                else
                {
                    return null;
                }
            }

            long lastPosition = reader.BaseStream.Position;
            string[] splits = sections[0].Split('\t');

            var severity = LogItemSeverity.DEBUG;
            Enum.TryParse(splits[0], out severity);

            DateTime timestamp = DateTime.ParseExact(splits[1], StringHelper.DefaultDateFormat,
                CultureInfo.InvariantCulture);

            int threadId = Convert.ToInt32(splits[2]);
            string threadName = splits.Length > 3 ? splits[3] : null;

            var record = new LogRecord(position, serialNumber, severity, timestamp, threadId,
                threadName,
                sections[2]);
            if (!string.IsNullOrWhiteSpace(sections[1]))
            {
                splits = sections[1].Split(',');
                if (splits.Length > 0)
                {
                    record.ContextValues = new SortedDictionary<string, object>();
                    foreach (string v in splits)
                    {
                        string[] pair = v.Split('=');
                        record.ContextValues.Add(pair[0], pair.Length > 1 ? pair[1] : null);
                    }
                }
            }
            return record;
        }

        #endregion Methods
    }
}